package ar.edu.caece.pl.asem.codegenerator;

public class PreDefinedFunctions {
	
	public final static StringBuffer sb = new StringBuffer(); 
	static {
		sb.append("; ***Comienzo rutina writeCRLF*** \n");
		sb.append("; \n");
		sb.append("; Imprime por pantalla un caracter <Enter> (<CR><LF>) \n");
		sb.append("; \n");
		sb.append("; Parametros: - \n");
		sb.append("; \n");
		sb.append("writeCRLF proc near \n");
		sb.append("\t push ax \n");
		    
		sb.append("\t mov al, 0Dh \n");
		sb.append("\t mov ah, 0Eh \n");
		sb.append("\t int 10h \n");     
		sb.append("\t mov al, 0Ah \n");
		sb.append("\t mov ah, 0Eh \n");
		sb.append("\t int 10h \n");     
		sb.append("\t pop ax \n");
		sb.append("\t ret \n");
		sb.append("writeCRLF endp \n");
		sb.append("; \n");
		sb.append("; ***Fin rutina writeCRLF*** \n");
		sb.append("; ***Comienzo rutina writeSTR*** \n");
		sb.append("; \n");
		sb.append("; Imprime por pantalla un string sin <Enter> al final \n");
		sb.append("; \n");
		sb.append("; Parametro entrada 1: direccion de memoria donde comienza el string a imprimir (word/via push del llamador) \n");
		sb.append("; Parametro entrada 2: cantidad de caracteres del string (word/via push del llamador) \n");
		sb.append("; \n");
		sb.append("writeSTR proc near \n");
		sb.append("\t push bp \n");
		sb.append("\t mov bp, sp \n");
		sb.append("\t push ax \n");
		sb.append("\t push bx \n");
		sb.append("\t push cx \n");
		sb.append("\t push si \n");
		sb.append("\t mov si, [bp+6]  ; a SI se le asigna el primer parametro (direccion) \n");
		sb.append("\t mov cx, [bp+4]  ; a CX se le asigna el segundo parametro (cantidad de caracteres) \n");
		sb.append("\t xor bx, bx \n");	    
		sb.append("loop: \n");    
		sb.append("\t mov al, [si] \n");
		sb.append("\t mov ah, 0Eh \n");
		sb.append("\t int 10h \n");     
		sb.append("\t inc bx \n");
		sb.append("\t inc si \n");
		sb.append("\t cmp bx, cx \n");
		sb.append("\t jne loop \n");
		sb.append("\t pop si \n");
		sb.append("\t pop cx \n");
		sb.append("\t pop bx \n");
		sb.append("\t pop ax \n");
		sb.append("\t pop bp \n");
		sb.append("\t ret 4 \n");
		sb.append("writeSTR endp \n");
		sb.append("; \n");
		sb.append("; ***Fin rutina writeSTR*** \n");
	
	
	
		sb.append("; ***Comienzo rutina writeNUM*** \n");
		sb.append("; \n");
		sb.append("; Imprime por pantalla un numero (word con signo) sin <Enter> al final \n");
		sb.append("; (usa rutina writeSTR) \n");
		sb.append("; \n");
		sb.append("; Parametro entrada 1: tipo de aritmetica -0000h=sin signo, 0001h=con signo- (word/via push del llamador) \n");
		sb.append("; Parametro entrada 2: numero a imprimir (word/via push del llamador) \n");
		sb.append("; \n");
		sb.append("writeNUM proc near \n");
		sb.append("\t push bp \n");
		sb.append("\t mov bp, sp \n");
		sb.append("\t sub sp, 1        ; \"variable local\" [bp-1] = signo (00h=positivo, 01h=negativo) \n");
		sb.append("\t sub sp, 6        ; \"variable local\" [bp-7] = espacio para imprimir (db 6 dup(?)) \n");
	
		sb.append("\t push ax \n");
		sb.append("\t push bx \n");
		sb.append("\t push cx \n");
		sb.append("\t push dx \n");
		sb.append("\t push si \n");
	
		sb.append("\t mov [bp-1], 00h \n");
		sb.append("\t mov ax, [bp+4] \n");
	
		sb.append("\t cmp [bp+6], 0 \n");
		sb.append("\t je comenzar      ; Si no es aritmetica con signo, comienza \n");
		sb.append("\t cmp ax, 0 \n");
		sb.append("\t jge comenzar     ; Si no es negativo, comienza \n");
		sb.append("\t neg ax           ; Realiza ax = -ax \n");
		sb.append("\t mov [bp-1], 01h \n");
	
		sb.append("comenzar: \n");
		sb.append("\t mov bx, 10 \n");
		sb.append("\t mov cx, 0 \n");
		sb.append("\t mov si, bp \n");
		sb.append("\t sub si, 8 \n");
	
		sb.append("proxdiv: \n");
		sb.append("\t dec si \n");
		sb.append("\t xor dx, dx \n");    
		sb.append("\t div bx \n");
		sb.append("\t add dl, 48 \n");
		sb.append("\t mov [si], dl \n");
		sb.append("\t inc cx \n");
		sb.append("\t cmp ax, 0 \n");
		sb.append("\t jnz proxdiv \n");
		    
		sb.append("\t cmp [bp-1], 00h \n");
		sb.append("\t jz mostrar \n");
		    
		sb.append("\t dec si \n");
		sb.append("\t mov [si], '-' \n");
		sb.append("\t inc cx \n");
	
		sb.append("mostrar: \n");    
		sb.append("\t push si \n");
		sb.append("\t push cx \n");
		sb.append("\t call writeSTR \n");
	
		sb.append("\t pop si \n");
		sb.append("\t pop dx \n");
		sb.append("\t pop cx \n");
		sb.append("\t pop bx \n");
		sb.append("\t pop ax \n");
	
		sb.append("\t mov sp, bp \n");   
		sb.append("\t pop bp \n");
		sb.append("\t ret 4 \n");
		sb.append("writeNUM endp \n");
		sb.append("; \n");
		sb.append("; ***Fin rutina writeNUM*** \n");
	
	
	
		sb.append("; ***Comienzo rutina readln*** \n");
		sb.append("; \n");
		sb.append("; Obtiene por teclado un numero (word con o sin signo) \n");
		sb.append("; (usa rutina writeSTR, notar que posee dos macros) \n");
		sb.append("; Solamente permite ingresar caracteres <0>..<9>, <->, <Backspace>, <Enter> (cuando corresponden) \n");
		sb.append("; No realiza control de overflow, ni permite <Control><Break> para cortar la ejecucion del programa \n");
		sb.append("; \n");
		sb.append("; Parametro entrada: tipo de aritmetica -0000h=sin signo, 0001h=con signo- (word/via push del llamador) \n");
		sb.append("; Parametro salida: numero obtenido (word/via pop del llamador) \n");
		sb.append("; (el llamador antes debera efectuar un push de un word para que esta rutina deje el resultado ahi) \n");
		sb.append("; \n");
		sb.append("dig macro digbase \n");
		sb.append("\t cmp al, digbase \n");
		sb.append("\t jl inicioread \n");
		sb.append("\t cmp al, '9' \n");
		sb.append("\t jg inicioread \n");
		sb.append("\t mov ah, 0Eh \n");
		sb.append("\t int 10h \n");     
		sb.append("\t mov [bp-1], 03h \n");
		sb.append("\t mov cl, al \n");
		sb.append("\t sub cl, 48 \n");
		sb.append("\t mov ax, si \n");
		sb.append("\t mov bx, 000Ah \n");
		sb.append("\t mul bx           ; AX = AX * 10 \n");
		sb.append("\t add ax, cx       ; AX = AX + CX (digito) \n");
		sb.append("\t mov si, ax \n");
		sb.append("endm \n");
		sb.append("writeBS macro \n");
		sb.append("\t mov ah, 0Eh \n");
		sb.append("\t int 10h \n");
		sb.append("\t mov al, ' ' \n");
		sb.append("\t int 10h \n");
		sb.append("\t mov al, 08h \n");
		sb.append("\t int 10h \n");     
		sb.append("endm \n");
		sb.append("readln proc near \n");
		sb.append("\t push bp \n");
		sb.append("\t mov bp, sp \n");
		sb.append("\t sub sp, 1        ; [bp-1] = estado (00h=inicio, 01h=solo 0, 02h=-, 03h=digitos) \n");
		sb.append("\t sub sp, 1        ; [bp-2] = signo (00h=positivo, 01h=negativo) \n");
	
		sb.append("\t push ax \n");
		sb.append("\t push bx \n");
		sb.append("\t push cx \n");
		sb.append("\t push dx \n");
		sb.append("\t push si \n");
		sb.append("\t mov [bp-1], 00h \n");
		sb.append("\t mov [bp-2], 00h \n");
		sb.append("\t mov si, 0000h    ; valor \n");
		sb.append("\t mov bx, 0 \n");
		sb.append("\t mov cx, 0 \n");
	
		sb.append("inicioread: \n");
		sb.append("\t mov ah, 0 \n");
		sb.append("\t int 16h \n");
		    
		sb.append("\t cmp [bp-1], 00h \n");
		sb.append("\t je estado0 \n");
		sb.append("\t cmp [bp-1], 01h \n");
		sb.append("\t je estado1 \n");
		sb.append("\t cmp [bp-1], 02h \n");
		sb.append("\t je estado2 \n");
		sb.append("\t cmp [bp-1], 03h \n");
		sb.append("\t je estado3 \n");
		    
		sb.append("estado0: \n");    
		sb.append("\t cmp al, 0Dh \n");
		sb.append("\t je inicioread \n");
		sb.append("\t cmp al, '0' \n");
		sb.append("\t jne estado0a \n");
		sb.append("\t mov [bp-1], 01h \n");
		sb.append("\t mov ah, 0Eh \n");
		sb.append("\t int 10h \n");     
		sb.append("\t jmp inicioread \n");
		sb.append("estado0a: \n");
		sb.append("\t cmp al, '-' \n");
		sb.append("\t jne estado0b \n");
		sb.append("\t cmp [bp+4], 0000h \n");
		sb.append("\t je inicioread \n");    
		sb.append("\t mov [bp-1], 02h \n");
		sb.append("\t mov [bp-2], 01h \n");
		sb.append("\t mov ah, 0Eh \n");
		sb.append("\t int 10h \n");     
		sb.append("\t jmp inicioread \n");
		sb.append("estado0b: \n");
		sb.append("\t dig '1' \n");
		sb.append("\t jmp inicioread \n");
	
		sb.append("estado1: \n");    
		sb.append("\t cmp al, 0Dh \n");
		sb.append("\t je finread \n");
		sb.append("\t cmp al, 08h \n");
		sb.append("\t jne inicioread \n");
		sb.append("\t writeBS \n");
		sb.append("\t mov [bp-1], 00h \n");
		sb.append("\t jmp inicioread \n");
	
		sb.append("estado2: \n");
		sb.append("\t cmp al, 0Dh \n");
		sb.append("\t je inicioread \n");
		sb.append("\t cmp al, 08h \n");
		sb.append("\t jne estado2a \n");
		sb.append("\t writeBS \n");
		sb.append("\t mov [bp-1], 00h \n");
		sb.append("\t mov [bp-2], 00h \n");
		sb.append("\t jmp inicioread \n");
		sb.append("estado2a: \n");    
		sb.append("\t dig '1' \n");
		sb.append("\t jmp inicioread \n");
	
		sb.append("estado3: \n");    
		sb.append("\t cmp al, 0Dh \n");
		sb.append("\t je finread \n");
		sb.append("\t cmp al, 08h \n");
		sb.append("\t jne estado3a \n");
		sb.append("\t writeBS \n");
		sb.append("\t mov ax, si \n");
		sb.append("\t mov dx, 0 \n");
		sb.append("\t mov bx, 000Ah \n");
		sb.append("\t div bx           ; AX = AX / 10 \n");
		sb.append("\t mov si, ax \n");
		sb.append("\t cmp si, 0 \n");
		sb.append("\t jne inicioread \n");
		sb.append("\t cmp [bp-2], 00h \n");
		sb.append("\t jne estado3bs1 \n");
		sb.append("\t mov [bp-1], 00h \n");
		sb.append("\t jmp inicioread \n");
		sb.append("estado3bs1: \n");
		sb.append("\t mov [bp-1], 02h \n");
		sb.append("\t jmp inicioread \n");
		sb.append("estado3a: \n");    
		sb.append("\t dig '0' \n");
		sb.append("\t jmp inicioread \n");
	
		sb.append("finread: \n");
		sb.append("\t cmp [bp-2], 00h \n");
		sb.append("\t je finread2 \n");
		sb.append("\t neg si \n");
		sb.append("finread2: \n");
		sb.append("\t mov [bp+6], si \n");
		sb.append("\t pop si \n");
		sb.append("\t pop dx \n");
		sb.append("\t pop cx \n");
		sb.append("\t pop bx \n");
		sb.append("\t pop ax \n");
		sb.append("\t mov sp, bp \n"); 
		sb.append("\t pop bp \n");    
		sb.append("\t ret 2 \n");
		sb.append("readln endp \n");
		sb.append("; \n");
		sb.append("; ***Fin rutina readln*** \n");
	}
}
